home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / madtrb10.arc / STACK.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-12-08  |  25.8 KB  |  546 lines

  1. Program Stack;
  2.  
  3. { *************************************************************************** }
  4. { *                                                                         * }
  5. { *          POLISH POSTFIX NOTATION EXPRESSION EVALUATION PROGRAM          * }
  6. { *                    using a Stack Data Structure                         * }
  7. { *                             Program #4                                  * }
  8. { *                                                                         * }
  9. { *                     Class: CS 367     Section: 4                        * }
  10. { *                         Instructor: Wiegand                             * }
  11. { *                                                                         * }
  12. { *                       Written by Chris Maeder                           * }
  13. { *                Edited and Compiled using Turbo Pascal                   * }
  14. { *                            on an IBM PC                                 * }
  15. { *                                                                         * }
  16. { *   DEFINITION:                                                           * }
  17. { *        A stack is a data structure which exhibits last-in/first-out     * }
  18. { *        behavior.  Elements are added to the top of the stack and only   * }
  19. { *        the top-most element element can be removed.  When the top-most  * }
  20. { *        element is removed then the second top-most element can be       * }
  21. { *        removed.  The operation of adding an element to the top of the   * }
  22. { *        stack is called Push.  That operation of removing the top-most   * }
  23. { *        element from the stack is called Pop.                            * }
  24. { *                                                                         * }
  25. { *   ALGORITHM:                                                            * }
  26. { *        A stack is implimented through the use of pointers, creating a   * }
  27. { *        linked list of elements with a pointer pointing to the top-most  * }
  28. { *        element.                                                         * }
  29. { *                                                                         * }
  30. { *                        STACK                                            * }
  31. { *                                                                         * }
  32. { *                     ------------                                        * }
  33. { *                    | Operand #1 |  <-----Top Pointer                    * }
  34. { *                     ------------                                        * }
  35. { *                          |                                              * }
  36. { *                          V                                              * }
  37. { *                     ------------                                        * }
  38. { *                    | Operand #2 |                                       * }
  39. { *                     ------------                                        * }
  40. { *                          |                                              * }
  41. { *                          V                                              * }
  42. { *                     ------------                                        * }
  43. { *                    | Operand #3 |                                       * }
  44. { *                     ------------                                        * }
  45. { *                          |                                              * }
  46. { *                          V                                              * }
  47. { *                     ------------                                        * }
  48. { *                    | Operand #4 |                                       * }
  49. { *                     ------------                                        * }
  50. { *                          |                                              * }
  51. { *                          V                                              * }
  52. { *                         Nil                                             * }
  53. { *                                                                         * }
  54. { *        A stack is used to evaluate expressions written in Polish        * }
  55. { *        postfix notation (PPN).  Operands are pushed onto the stack      * }
  56. { *        until a operator is received.  Then the stack is popped twice    * }
  57. { *        and the two values are operated upon by the operator and the     * }
  58. { *        result is pushed back onto the top of the stack.  When the       * }
  59. { *        expression is finished being evaluated the final result is       * }
  60. { *        popped off of the stack and then printed.                        * }
  61. { *                                                                         * }
  62. { *        If an error is encountered during the evaluation of the          * }
  63. { *        expression an error message is printed and the next expression   * }
  64. { *        is then evaluated.                                               * }
  65. { *                                                                         * }
  66. { *        Valid mathematical operators are:                                * }
  67. { *                                                                         * }
  68. { *                      Addition                                           * }
  69. { *                      Subtraction                                        * }
  70. { *                      Multiplication                                     * }
  71. { *                      Division                                           * }
  72. { *                      Exponentiation                                     * }
  73. { *                                                                         * }
  74. { *   PURPOSE:                                                              * }
  75. { *        1. Print program heading.                                        * }
  76. { *        2. Evaluate Polish postfix notation (PPN) expression using a     * }
  77. { *           stack data structure.                                         * }
  78. { *        3. Implement the stack data structure using pointers.            * }
  79. { *        4. Operate on the stack data structure with the following        * }
  80. { *           functions and procedures.                                     * }
  81. { *           a. CreateStack-create a stack, setting top pointer to Nil.    * }
  82. { *           b. Push-add an element to top of stack.                       * }
  83. { *           c. EmptyStack-determine if the stack is empty.                * }
  84. { *           d. Pop-remove an element from the top of the stack.           * }
  85. { *           e. DeleteStack-remove all elements in a stack, setting top    * }
  86. { *              pointer to Nil.                                            * }
  87. { *        5. Check for malformed PPN expressions.                          * }
  88. { *                                                                         * }
  89. { *   INPUT/OUTPUT:                                                         * }
  90. { *        1. Print program heading.                                        * }
  91. { *        2. Read the PPN expression out of the data file.                 * }
  92. { *           a. Echo print the PPN expression.                             * }
  93. { *        3. Starting from the left, pick off entries out of the PPN       * }
  94. { *           expression.  Entries are assumed to be seperated by a         * }
  95. { *           single blank.                                                 * }
  96. { *           a. Operand entry                                              * }
  97. { *              i.   Push operand onto top of stack.                       * }
  98. { *           b. Operator entry                                             * }
  99. { *              i.   Pop the stack twice to get two operands.              * }
  100. { *              ii.  Using the operator, operate on the two operands.      * }
  101. { *              iii. Push the result back onto the stack.                  * }
  102. { *        4. After the expression has been evaluated, print the result     * }
  103. { *           of the expression.                                            * }
  104. { *        5. Otherwise print an error message if it was found that         * }
  105. { *           a. Invalid character in the expression.                       * }
  106. { *           b. Malformed PPN expression.                                  * }
  107. { *                                                                         * }
  108. { *************************************************************************** }
  109.  
  110. Const
  111.   MAX_ENTRY_SIZE=80;                             { maximum size of the PPN expression }
  112.   MAX_NEG_INT=-32767;                            { maximum negative integer, used in flagging an error }
  113.   FILE_NAME='Stack.Fil';                         { input file name which contains PPN expressions requiring evaluation }
  114.   L_PRINT=False;                                 { a boolean used to control the re-direction of output to the printer }
  115.  
  116. Type
  117.   StackElementPtr=^StackElementType;             { a pointer which points to the data record type 'StackElementType' }
  118.   StackElementType=                              { stack element data record type }
  119.     Record
  120.       NumericData:Real;                          { field used to store real numbers }
  121.       NextElement:StackElementPtr;               { field used to store next element pointer }
  122.     End; { StackElementType }
  123.   EntryString=String[MAX_ENTRY_SIZE];            { a string type used to store expressions and entries }
  124.  
  125. Var
  126.   Error:Boolean;                                 { an error flag which is used to tell the program that there is
  127.                                                    something wrong with the PPN expression }
  128.   Top:StackElementPtr;                           { a pointer used to point to the top of the stack }
  129.   HoldPtr:Integer;                               { a temporary pointer used in the re-directing of the output
  130.                                                    from the screen to the printer }
  131.  
  132.  
  133.  
  134. Procedure PrintHeading;
  135.  
  136. { This procedure prints a heading for the program. }
  137.  
  138. Begin   { PrintHeading }
  139.   WriteLn;
  140.   WriteLn('POLISH POSTFIX NOTATION EXPRESSION EVALUATION PROGRAM');
  141.   WriteLn;
  142. End;    { PrintHeading }
  143.  
  144.  
  145.  
  146. Procedure RemoveFirstEntryFromString(Var Text:EntryString);
  147.  
  148. { This procedure removes the first text entry from the passed text string and
  149.   returns the new truncated text string.  The text entries in the passed text
  150.   string are assumed to be delinated by one space.  See the following
  151.   example.
  152.  
  153.          Passed:    Entry1  Entry2  Entry3
  154.          Returned:  Entry2  Entry3                      }
  155.  
  156. Begin   { RemoveFirstEntryFromString }
  157.   If Pos(' ',Text)=0 Then
  158.     Text:=''
  159.   Else
  160.     Text:=Copy(Text,(Pos(' ',Text)+1),(Length(Text)-Pos(' ',Text)));
  161. End;    { RemoveFirstEntryFromString }
  162.  
  163.  
  164.  
  165. Procedure ReturnFirstEntryFromString(Var Text:EntryString);
  166.  
  167. { This procedure removes the first text entry from the passed text string and
  168.   returns the first text entry.  The text entries in the passed text string
  169.   are assumed to be delinated by one space.  See the following example.
  170.  
  171.          Passed:    Entry1  Entry2  Entry3
  172.          Returned:  Entry1                              }
  173.  
  174. Begin   { ReturnFirstEntryFromString }
  175.   If Pos(' ',Text)<>0 Then
  176.     Text:=Copy(Text,1,(Pos(' ',Text)-1));
  177. End;    { ReturnFirstEntryFromString }
  178.  
  179.  
  180.  
  181. Procedure DetermineEntryInExpression(Var Expression,Entry:EntryString);
  182.  
  183. { The entries in the passed PPN expression are assumed to be delinated by one
  184.   space.  This procedure removes the front lying entry from the expression and
  185.   returns the now shortened expression and the expression's entry to the
  186.   calling routine.  An example follows:
  187.  
  188.         Passed Values
  189.           Expression : Entry1 Entry2 Entry3
  190.           Entry      :
  191.  
  192.         Returned Values
  193.           Expression : Entry2 Entry3
  194.           Entry      : Entry1
  195.  
  196.   If the returned expression is empty then a blank entry is returned. }
  197.  
  198. Begin   { DetermineEntryInExpression }
  199.   Entry:=Expression;
  200.   ReturnFirstEntryFromString(Entry);
  201.   RemoveFirstEntryFromString(Expression);
  202. End;    { DetermineEntryInExpression }
  203.  
  204.  
  205.  
  206. Procedure CreateStack(Var StackTopPtr:StackElementPtr);
  207.  
  208. { This procedure is used at program start-up to initialize the stack's top
  209.   pointer to nil.  This corresponds to the stack being empty. }
  210.  
  211. Begin   { CreateStack }
  212.   Top:=Nil;
  213. End;    { CreateStack }
  214.  
  215.  
  216.  
  217.  
  218. Procedure DisposeStack(Var StackTopPtr:StackElementPtr);
  219.  
  220. { This procedure is used after a PPN expression has been ( or was tried to
  221.   be ) evaluated.  It removes any remaining stack elements and sets the
  222.   top of the stack pointer to point to nil. }
  223.  
  224. Var
  225.   TempStackElementPtr:StackElementPtr;           { a temporary pointer to a stack element }
  226.  
  227. Begin   { DisposeStack }
  228.   While StackTopPtr<>Nil Do
  229.     Begin
  230.       TempStackElementPtr:=StackTopPtr;          { temporarily save reference to top stack element }
  231.       StackTopPtr:=StackTopPtr^.NextElement;     { have the top stack pointer point to the next element in the stack }
  232.       Dispose(TempStackElementPtr);              { dispose of the previous top stack pointer }
  233.     End; { While StackTopPtr }
  234. End;    { DiposeStack }
  235.  
  236.  
  237.  
  238. Function EmptyStack(StackTopPtr:StackElementPtr):Boolean;
  239.  
  240. { This function is used to check if the present stack is empty.  If the stack
  241.   is empty this function returns as true, else it returns as false. }
  242.  
  243. Begin   { EmptyStack }
  244.   If StackTopPtr=Nil Then
  245.     EmptyStack:=True                             { the present stack is empty }
  246.   Else
  247.     EmptyStack:=False;                           { the present stack is not empty }
  248. End;    { EmptyStack }
  249.  
  250.  
  251.  
  252. Function LegalNumericEntry(StringEntry:EntryString):Boolean;
  253.  
  254. { This function determines if the passed string entry is a legal real or
  255.   integer number.  If the passed string entry is legal this funstion returns
  256.   as true, else it returns as false. }
  257.  
  258. Var
  259.   NumericEntry:Real;                             { used to temporarily store the converted string entry }
  260.   ErrorCode:Integer;                             { an error code used in the string procedure 'Val' }
  261.  
  262. Begin   { LegalNumericEntry }
  263.   Val(StringEntry,NumericEntry,ErrorCode);       { convert the string entry into a numeric entry.  Error code is set to the
  264.                                                    position of the first character in error. }
  265.   If ErrorCode=0 Then
  266.     LegalNumericEntry:=True                      { legal numeric entry }
  267.   Else
  268.     LegalNumericEntry:=False;                    { illegal numeric entry }
  269. End;    { LegalNumericEntry }
  270.  
  271.  
  272.  
  273. Procedure Push(NumericStackEntry:Real);
  274.  
  275. { This procedure first transfers the number into a newly stack
  276.   element record.  Finally it adds this stack element to the top of the
  277.   present stack while resetting the top stack pointer to point to it. }
  278.  
  279. Var
  280.   StackElement:StackElementPtr; { a pointer to a newly formed stack element }
  281.  
  282. Begin   { Push }
  283.   New(StackElement);                             { create a new record to store a pushed stack element }
  284.   StackElement^.NumericData:=NumericStackEntry;  { transfer numeric stack entry into stack element record }
  285.   StackElement^.NextElement:=Top;                { insert stack element into the top of the present stack }
  286.   Top:=StackElement;                             { reset top stack pointer to point to top of the stack }
  287. End;    { Push }
  288.  
  289.  
  290.  
  291. Procedure Pop(Var NumericStackEntry:Real);
  292.  
  293. { This procedure removes an element from the top of the stack and passes the
  294.   element back to the calling routine.  If the stack happens to be empty then
  295.   the procedure  flags the error by returning an empty element (equal to
  296.   negative maximum integer).  This then tells the calling routine that there
  297.   is an error in the PPN expression. }
  298.  
  299. Const
  300.   EMPTY=MAX_NEG_INT;
  301.  
  302. Var
  303.   TempStackElementPtr:StackElementPtr;           { a temporary pointer to the stack element that has just been taken off
  304.                                                    the top of the stack }
  305.  
  306. Begin   { Pop }
  307.   If Not EmptyStack(Top) Then                    { check if the stack is not empty }
  308.     Begin
  309.       NumericStackEntry:=Top^.NumericData;       { pull numeric data out of the topmost stack element }
  310.       TempStackElementPtr:=Top;                  { temporarily save reference to top stack element }
  311.       Top:=Top^.NextElement;                     { have the top stack pointer point to the next element in the stack }
  312.       Dispose(TempStackElementPtr);              { dispose of the previous top stack element }
  313.     End { if Not EmptyStack }
  314.   Else
  315.     NumericStackEntry:=EMPTY;                    { set a flag to tell the calling routine that procedure could not remove
  316.                                                    an element off of the empty stack }
  317. End;    { Pop }
  318.  
  319.  
  320.  
  321. Procedure Addition;
  322.  
  323. { This procedure pops the two topmost elements from the stack, adds them
  324.   together and pushes the result back onto the stack.  If this procedure
  325.   detects that an error occured when trying to pop the elements off of the
  326.   stack, it flags an error and prints the appropriate error message. }
  327.  
  328. Var
  329.   FirstEntry,SecondEntry:Real;                   { used to stare the elements removed from the top of the stack }
  330.  
  331. Begin   { Addition }
  332.   Pop(FirstEntry);                               { remove topmost element from the stack }
  333.   Pop(SecondEntry);                              { remove second topmost element from the stack }
  334.   If (FirstEntry<>MAX_NEG_INT) And (SecondEntry<>MAX_NEG_INT) Then { check for error in popping elements off of stack }
  335.     Push(SecondEntry+FirstEntry)
  336.   Else
  337.     Error:=True;
  338. End;    { Addition }
  339.  
  340.  
  341.  
  342. Procedure Subtraction;
  343.  
  344. { This procedure pops the two topmost elements from the stack, subtracts the
  345.   first entry from the second entry and pushes the result back onto the stack.
  346.   If this procedure detects that an error occured when trying to pop the
  347.   elements off of the stack, it flags an error and prints the appropriate
  348.   error message. }
  349.  
  350. Var
  351.   FirstEntry,SecondEntry:Real;                   { used to stare the elements removed from the top of the stack }
  352.  
  353. Begin   { Subtraction }
  354.   Pop(FirstEntry);                               { remove topmost element from the stack }
  355.   Pop(SecondEntry);                              { remove second topmost element from the stack }
  356.   If (FirstEntry<>MAX_NEG_INT) And (SecondEntry<>MAX_NEG_INT) Then { check for error in popping elements off of stack }
  357.     Push(SecondEntry-FirstEntry)
  358.   Else
  359.     Error:=True;
  360. End;    { Subtraction }
  361.  
  362.  
  363.  
  364. Procedure Multiplication;
  365.  
  366. { This procedure pops the two topmost elements from the stack, multiplies them
  367.   together and pushes the result back onto the stack.  If this procedure
  368.   detects that an error occured when trying to pop the elements off of the
  369.   stack, it flags an error and prints the appropriate error message. }
  370.  
  371. Var
  372.   FirstEntry,SecondEntry:Real;                   { used to stare the elements removed from the top of the stack }
  373.  
  374. Begin   { Multiplication }
  375.   Pop(FirstEntry);                               { remove topmost element from the stack }
  376.   Pop(SecondEntry);                              { remove second topmost element from the stack }
  377.   If (FirstEntry<>MAX_NEG_INT) And (SecondEntry<>MAX_NEG_INT) Then { check for error in popping elements off of stack }
  378.     Push(SecondEntry*FirstEntry)
  379.   Else
  380.     Error:=True;
  381. End;    { Multiplication }
  382.  
  383.  
  384.  
  385. Procedure Division;
  386.  
  387. { This procedure pops the two topmost elements from the stack, divides the
  388.   first entry into the second entry and pushes the result back onto the stack.
  389.   If this procedure detects that an error occured when trying to pop the
  390.   elements off of the stack, it flags an error and prints the appropriate
  391.   error message. }
  392.  
  393. Var
  394.   FirstEntry,SecondEntry:Real;                   { used to stare the elements removed from the top of the stack }
  395.  
  396. Begin   { Division }
  397.   Pop(FirstEntry);                               { remove topmost element from the stack }
  398.   Pop(SecondEntry);                              { remove second topmost element from the stack }
  399.   If (FirstEntry<>MAX_NEG_INT) And (SecondEntry<>MAX_NEG_INT) Then { check for error in popping elements off of stack }
  400.     Push(SecondEntry/FirstEntry)
  401.   Else
  402.     Error:=True;
  403. End;    { Division }
  404.  
  405.  
  406.  
  407. Procedure Exponentiation;
  408.  
  409. { This procedure pops the two topmost elements from the stack, raises the
  410.   second entry to the power of the first entry and pushes the result back onto
  411.   the stack.  If this procedure detects that an error occured when trying to
  412.   pop the elements off of the stack, it flags an error and prints the
  413.   appropriate error message. }
  414.  
  415. Var
  416.   FirstEntry,SecondEntry:Real;                   { used to stare the elements removed from the top of the stack }
  417.  
  418. Begin   { Exponentiation }
  419.   Pop(FirstEntry);                               { remove topmost element from the stack }
  420.   Pop(SecondEntry);                              { remove second topmost element from the stack }
  421.   If (FirstEntry<>MAX_NEG_INT) And (SecondEntry<>MAX_NEG_INT) Then { check for error in popping elements off of stack }
  422.     Push(Exp(FirstEntry*Ln(SecondEntry)))
  423.   Else
  424.     Error:=True;
  425. End;    { Exponentiation }
  426.  
  427.  
  428.  
  429. Procedure WriteResultOfExpression;
  430.  
  431. { This procedure writes the evaluation results from the PPN expression. }
  432.  
  433. Begin   { WriteResultOfExpression }
  434.   WriteLn;
  435.   WriteLn('The result of the above expression is : ',Top^.NumericData);
  436. End;    { WriteResultOfExpression }
  437.  
  438.  
  439.  
  440. Procedure Evaluate_PPN_Expression(Expression:EntryString);
  441.  
  442. { This procedure controls the evaluation of the passed PPN expression.  It
  443.   passes control to specific procedures when a valid operator is evaluated
  444.   within the expression.  When a valid operand is evaluated within the
  445.   expression it is pushed onto the stack.
  446.  
  447.   Valid operators are +,-,*,/, and ^.  A valid operand is any real or integer
  448.   number with a maximum of 10 places including the decimal point if one
  449.   exists.  Blanks seperate operators from operands.  All arithmetic is real.
  450.   A negative number has a minus sign immediately preceeding it.
  451.  
  452.   Examples of PPN expressions are:
  453.  
  454.         PPN Expression               Equivalent Algebraic Expression
  455.         --------------               -------------------------------
  456.              2 5 -                                2-5
  457.  
  458.              6 2 /                                6/2
  459.                                                    2
  460.              4 2 ^                                4     }
  461.  
  462. Var
  463.   Entry:EntryString;                             { used to store an entry from within the PPN expression }
  464.   NumericStackEntry:Real;                        { used to store the converted string stack entry }
  465.   ErrorCode:Integer;                             { an error code used in the string procedure 'Val' }
  466.  
  467. Begin   { Evaluate_PPN_Expression }
  468.   Error:=False;                                  { set error flag to false }
  469.   DetermineEntryInExpression(Expression,Entry);  { pull first entry out of the PPN expression }
  470.   While (Entry<>'') And Not Error Do
  471.     Begin  { determine entry }
  472.       If (Entry='+') Or (Entry='-') Or (Entry='*') Or (Entry='/') Or (Entry='^') Then { check for valid operator }
  473.         Case Entry Of                            { perform operation }
  474.           '+' : Addition;
  475.           '-' : Subtraction;
  476.           '*' : Multiplication;
  477.           '/' : Division;
  478.           '^' : Exponentiation;
  479.         End { Case Entry }
  480.       Else                                       { perform operation }
  481.         If LegalNumericEntry(Entry) Then
  482.           Begin
  483.             Val(Entry,NumericStackEntry,ErrorCode); { convert the StringStackEntry into a NumericStackEntry. ErrorCode is
  484.                                                       set to the position of the first character in error. }
  485.             Push(NumericStackEntry);             { push valid operand onto stack }
  486.           End { If LegalNumericEntry }
  487.         Else                                     { malformed PPN expression }
  488.           Error:=True;
  489.       DetermineEntryInExpression(Expression,Entry);
  490.     End; { While (Entry }
  491.     If Error Or (Top^.NextElement<>Nil) Then
  492.       Begin
  493.         WriteLn;
  494.         WriteLn('There was an error detected in the above expression.');
  495.         Error:=True;
  496.       End; { If Top^.NextElement }
  497.   If Not Error Then
  498.     WriteResultOfExpression;
  499.   DisposeStack(Top);
  500. End;    { Evaluate_PPN_Expression }
  501.  
  502.  
  503.  
  504. Procedure ReadInputFile;
  505.  
  506. { This procedure reads expressions written in Polish postfix notation (PPN)
  507.   from the declared file.  Each file entry in the declared file is a complete
  508.   PPN expression.
  509.  
  510.   Once the PPN entry is read from the file the entry is then passed to a
  511.   procedure which evaluates and prints the results of the PPN expression. }
  512.  
  513. Var
  514.   DataFile:Text;                                 { text file }
  515.   FileEntry:EntryString;                         { a string used to store the file entry for evaluation }
  516.  
  517. Begin   { ReadInputFile }
  518.   Assign(DataFile,FILE_NAME);                    { assign to a disk file }
  519.   Reset(DataFile);                               { open the file for reading }
  520.   Repeat                                         { read in the file entries }
  521.     ReadLn(DataFile,FileEntry);
  522.     WriteLn;
  523.     WriteLn;
  524.     WriteLn;
  525.     WriteLn;
  526.     WriteLn('Polish postfix notation expression : ');
  527.     WriteLn;
  528.     WriteLn('     ',FileEntry);
  529.     Evaluate_PPN_Expression(FileEntry);          { pass PPN expression to be evaluated }
  530.   Until Eof(DataFile);
  531.   Close(DataFile);                               { close the disk file }
  532. End;    { ReadInputFile }
  533.  
  534.  
  535.  
  536. Begin   { Main program }
  537.   HoldPtr:=ConOutPtr;                            { temporarily store current output address }
  538.   If L_PRINT Then
  539.     ConOutPtr:=LstOutPtr;                        { re-direct output to the printer }
  540.   PrintHeading;
  541.   CreateStack(Top);
  542.   ReadInputFile;
  543.   ConOutPtr:=HoldPtr;                            { reset output device address }
  544. End.    { Main program }
  545.  
  546.